package jnpf.engine.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.ImmutableList;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.base.vo.PageListVO;
import jnpf.base.vo.PaginationVO;
import jnpf.constant.MsgCode;
import jnpf.constant.PermissionConst;
import jnpf.engine.entity.*;
import jnpf.engine.enums.FlowNodeTypeEnum;
import jnpf.engine.enums.FlowTaskStatusEnum;
import jnpf.engine.model.*;
import jnpf.engine.model.flowbefore.*;
import jnpf.engine.model.flowcandidate.FlowCandidateUserModel;
import jnpf.engine.model.flowcandidate.FlowCandidateVO;
import jnpf.engine.model.flowcandidate.FlowRejectVO;
import jnpf.engine.model.flowengine.AddMultiFlowModel;
import jnpf.engine.model.flowengine.FlowModel;
import jnpf.engine.model.flowengine.shuntjson.childnode.ChildNode;
import jnpf.engine.model.flowengine.shuntjson.childnode.FuncConfig;
import jnpf.engine.model.flowengine.shuntjson.childnode.MsgConfig;
import jnpf.engine.model.flowengine.shuntjson.childnode.Properties;
import jnpf.engine.model.flowengine.shuntjson.nodejson.ChildNodeList;
import jnpf.engine.model.flowengine.shuntjson.nodejson.ConditionList;
import jnpf.engine.model.flowmessage.FlowMsgModel;
import jnpf.engine.model.flowtask.FlowTaskListModel;
import jnpf.engine.model.flowtask.PaginationFlowTask;
import jnpf.engine.model.flowtask.TaskNodeModel;
import jnpf.engine.service.*;
import jnpf.engine.util.*;
import jnpf.exception.WorkFlowException;
import jnpf.permission.entity.UserEntity;
import jnpf.permission.entity.UserRelationEntity;
import jnpf.permission.model.user.UserIdListVo;
import jnpf.permission.service.UserService;
import jnpf.util.*;
import jnpf.util.visiual.JnpfKeyConsts;
import org.apache.logging.log4j.util.Strings;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static jnpf.engine.custom.constants.GlobalProcessVariableConstants.*;
import static jnpf.engine.util.BpmnModelUtils.*;

/**
 * 待我审核
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2019年9月27日 上午9:18
 */
@Tag(name = "待我审核", description = "FlowBefore")
@RestController
@RequestMapping("/api/workflow/Engine/FlowBefore")
public class FlowBeforeController implements InitializingBean {


    private static final Logger log = LoggerFactory.getLogger(FlowBeforeController.class);
    @Autowired
    private ServiceAllUtil serviceUtil;
    @Autowired
    private UserProvider userProvider;
    @Autowired
    private FlowTaskUtil flowTaskUtil;
    @Autowired
    private FlowTaskService flowTaskService;
    @Autowired
    private FlowTemplateJsonService flowTemplateJsonService;
    @Autowired
    private FlowTaskOperatorService flowTaskOperatorService;
    @Autowired
    private FlowTaskOperatorRecordService flowTaskOperatorRecordService;
    @Autowired
    private FlowTaskNodeService flowTaskNodeService;
    @Autowired
    private FlowTaskNewService flowTaskNewService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private HistoryService historyService;
    @Resource
    private UserService userService;
    @Resource
    private FlowMsgUtil flowMsgUtil;

    private static ServiceAllUtil staticServiceUtil;




    @Operation(summary = "待我审核关注-取关")
    @PostMapping("/ShareEx/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult shareEx(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        return flowTaskNewService.shareEx(id);
    }
    @Operation(summary = "节点重试" )
    @GetMapping(value = "/tree/{id}/nodeRetry" )
    public ActionResult taskNode(@PathVariable("id" ) String id, String nodeId) {
        HistoricActivityInstance historicActivityInstance = historyService.createHistoricActivityInstanceQuery().activityInstanceId(nodeId).singleResult();
        String activityId = historicActivityInstance.getActivityId();
        String processDefinitionId = historicActivityInstance.getProcessDefinitionId();
        Process bpmnModelMainProcess = getBpmnModelMainProcess(processDefinitionId);
        String attributeValueByTaskDefinitionKey = getAttributeValueByTaskDefinitionKey(bpmnModelMainProcess, activityId, "");
        jnpf.engine.model.flowengine.shuntjson.childnode.Properties properties = JSONObject.parseObject(attributeValueByTaskDefinitionKey, new TypeReference<jnpf.engine.model.flowengine.shuntjson.childnode.Properties>() {
        });
        FuncConfig httpInitFuncConfig = properties.getHttpInitFuncConfig();
        FlowTaskOperatorRecordService flowTaskOperatorRecordService = SpringContextHolder.getBean(FlowTaskOperatorRecordService.class);
        LambdaQueryWrapper<FlowTaskOperatorRecordEntity> flowTaskOperatorRecordEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        flowTaskOperatorRecordEntityLambdaQueryWrapper.eq(FlowTaskOperatorRecordEntity::getTaskId,historicActivityInstance.getProcessInstanceId());
        UserTask firstNode = getFirstNode(bpmnModelMainProcess);
        flowTaskOperatorRecordEntityLambdaQueryWrapper.eq(FlowTaskOperatorRecordEntity::getNodeCode,firstNode.getId());
        FlowTaskOperatorRecordEntity flowTaskOperatorRecordEntity = flowTaskOperatorRecordService.list(flowTaskOperatorRecordEntityLambdaQueryWrapper).get(0);
        FlowModel flowModel = new FlowModel();
        Properties applyProperties = getFirstNodeProperty(processDefinitionId);
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(historicActivityInstance.getProcessInstanceId()).singleResult();
        Map<String, Object> infoData = flowTaskUtil.infoData(applyProperties.getFormId(), historicProcessInstance.getBusinessKey());
        flowModel.setFormData(infoData);

        FlowTaskOperatorRecordDTO flowTaskOperatorRecordDTO = new FlowTaskOperatorRecordDTO();
        flowTaskOperatorRecordDTO.setAssignee(flowTaskOperatorRecordEntity.getHandleId());
        flowTaskOperatorRecordDTO.setProcessInstanceId(flowTaskOperatorRecordEntity.getTaskId());
        flowTaskOperatorRecordDTO.setTaskId(flowTaskOperatorRecordEntity.getTaskNodeId());
        properties.getHttpInitFuncConfig().setOn(Boolean.TRUE);
        flowMsgUtil.event(10, properties, flowTaskOperatorRecordDTO, flowModel,null, Strings.EMPTY);
        return ActionResult.success("操作成功!");
    }


    @Operation(summary = "日志详情" )
    @GetMapping("/tree/{id}" )
    public ActionResult<TreeCommentMain> list(@PathVariable("id" ) String id) {
        HistoricProcessInstance historicProcessInstance=null;
            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult();
            if(historicTaskInstance==null){
                historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(id).includeProcessVariables().singleResult();
                if(historicProcessInstance==null){
                    historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(id).includeProcessVariables().singleResult();
                }
            }
            else{
                String processInstanceId = historicTaskInstance.getProcessInstanceId();
                historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).includeProcessVariables().singleResult();
            }
            TreeCommentMain treeCommentMain = new TreeCommentMain();
        List<TreeCommentSub> treeCommentSubList = new ArrayList<>();
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(historicProcessInstance.getId()).list();

        Process bpmnModelMainProcess = getBpmnModelMainProcess(historicProcessInstance.getProcessDefinitionId());
        Collection<FlowElement> flowElements = bpmnModelMainProcess.getFlowElements();
        for (FlowElement flowElement : flowElements) {
            if(flowElement instanceof StartEvent) {

            }
        }


        List<String> userIds= new ArrayList<>();
        userIds.add(historicProcessInstance.getStartUserId());
        List<String> nodeUserIds = new ArrayList<>();
        for (HistoricActivityInstance historicActivityInstance : list) {
            if(historicActivityInstance.getActivityType().equals("userTask")){
                nodeUserIds.add(historicActivityInstance.getAssignee());
            }
        }
        userIds.addAll(nodeUserIds);
        userIds=CollUtil.distinct(userIds);
        List<UserEntity> userList = userService.getListByUserIds(userIds);
        LambdaQueryWrapper<FlowTaskOperatorRecordEntity> lambdaQueryWrapper= new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FlowTaskOperatorRecordEntity::getTaskId,historicProcessInstance.getId());
        List<FlowTaskOperatorRecordEntity> recordEntityList = flowTaskOperatorRecordService.list(lambdaQueryWrapper);
        FlowEventLogService flowEventLogService = SpringContextHolder.getBean(FlowEventLogService.class);
        for (HistoricActivityInstance historicActivityInstance : list) {
            if("startEvent".equals(historicActivityInstance.getActivityType())){
//                TreeCommentSub treeCommentSub = new TreeCommentSub();
//                treeCommentSub.setTaskId(historicProcessInstance.getId());
//                treeCommentSub.setNodeCode(historicActivityInstance.getActivityId());
//                treeCommentSub.setNodeType(historicActivityInstance.getActivityType());
//                treeCommentSub.setNodeName(historicActivityInstance.getActivityName());
//                treeCommentSub.setResultType(3);
//                treeCommentSub.setErrorMsg("");
//                treeCommentSub.setStartTime(historicActivityInstance.getStartTime().getTime());
//                if(historicActivityInstance.getEndTime()!=null){
//                    treeCommentSub.setEndTime(historicActivityInstance.getEndTime().getTime());
//                }
//                treeCommentSub.setParentId("0");
//                treeCommentSub.setIsRetry(true);
//                treeCommentSub.setType(1);
//                treeCommentSub.setId(historicActivityInstance.getId());
//                HistoricProcessInstance finalHistoricProcessInstance = historicProcessInstance;
//                UserEntity entity = userList.stream().filter(t -> finalHistoricProcessInstance.getStartUserId().equals(t.getId())).findFirst().get();
//                UserInfoModel userInfoModel = new UserInfoModel();
//                userInfoModel.setAccount(entity.getRealName() + "/" + entity.getAccount());
//                userInfoModel.setHeadIcon(UploaderUtil.uploaderImg(entity.getHeadIcon()));
//                List<UserInfoModel> userInfoModelList= new ArrayList<>();
//                userInfoModelList.add(userInfoModel);
//                treeCommentSub.setUserInfoModel(userInfoModelList);
//
////                List<FlowTaskOperatorRecordEntity> collect = recordEntityList.stream().filter(t -> t.getTaskNodeId().equals(historicActivityInstance.getTaskId())).collect(Collectors.toList());
////                if(CollUtil.isNotEmpty(collect)){
////                    FlowTaskOperatorRecordEntity flowTaskOperatorRecordEntity = collect.get(0);
////                    treeCommentSub.setSignImg(flowTaskOperatorRecordEntity.getSignImg());
////                    treeCommentSub.setHandleOpinion(flowTaskOperatorRecordEntity.getHandleOpinion());
////                    treeCommentSub.setFileList(flowTaskOperatorRecordEntity.getFileList());
////                }
//                treeCommentSubList.add(treeCommentSub);
            }
            else if("userTask".equals(historicActivityInstance.getActivityType())){
                TreeCommentSub treeCommentSub = new TreeCommentSub();
                treeCommentSub.setTaskId(historicProcessInstance.getId());
                treeCommentSub.setNodeCode(historicActivityInstance.getActivityId());
                treeCommentSub.setNodeType(historicActivityInstance.getActivityType());
                treeCommentSub.setNodeName(historicActivityInstance.getActivityName());
                treeCommentSub.setResultType(3);
                treeCommentSub.setErrorMsg("");
                treeCommentSub.setStartTime(historicActivityInstance.getStartTime().getTime());
                if(historicActivityInstance.getEndTime()!=null){
                    treeCommentSub.setEndTime(historicActivityInstance.getEndTime().getTime());
                }
                treeCommentSub.setParentId("0");
                treeCommentSub.setIsRetry(false);
                treeCommentSub.setType(1);
                treeCommentSub.setId(historicActivityInstance.getId());
                HistoricProcessInstance finalHistoricProcessInstance = historicProcessInstance;
                UserEntity entity = userList.stream().filter(t -> finalHistoricProcessInstance.getStartUserId().equals(t.getId())).findFirst().get();
                UserInfoModel userInfoModel = new UserInfoModel();
                userInfoModel.setAccount(entity.getRealName() + "/" + entity.getAccount());
                userInfoModel.setHeadIcon(UploaderUtil.uploaderImg(entity.getHeadIcon()));
                List<UserInfoModel> userInfoModelList= new ArrayList<>();
                userInfoModelList.add(userInfoModel);
                treeCommentSub.setUserInfoModel(userInfoModelList);

                List<FlowTaskOperatorRecordEntity> collect = recordEntityList.stream().filter(a -> historicActivityInstance.getTaskId().equals(a.getTaskNodeId())).collect(Collectors.toList());
                if(CollUtil.isNotEmpty(collect)){
                    FlowTaskOperatorRecordEntity flowTaskOperatorRecordEntity = collect.get(0);
                    treeCommentSub.setSignImg(flowTaskOperatorRecordEntity.getSignImg());
                    treeCommentSub.setHandleOpinion(flowTaskOperatorRecordEntity.getHandleOpinion());
                    treeCommentSub.setFileList(flowTaskOperatorRecordEntity.getFileList());
                }

                treeCommentSubList.add(treeCommentSub);
            }
            else if("manualTask".equals(historicActivityInstance.getActivityType())){
                String attributeValueByTaskDefinitionKey = getAttributeValueByTaskDefinitionKey(bpmnModelMainProcess, historicActivityInstance.getActivityId(), "");
                Properties properties = JSONObject.parseObject(attributeValueByTaskDefinitionKey, new TypeReference<Properties>() {
                });
                String nodeType = properties.getNodeType();
                if(FlowNodeTypeEnum.HTTP_TASK.getType().equals(nodeType)){
                    //
                    LambdaQueryWrapper<FlowTaskOperatorRecordEntity> flowTaskOperatorRecordEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    flowTaskOperatorRecordEntityLambdaQueryWrapper.eq(FlowTaskOperatorRecordEntity::getTaskId,historicProcessInstance.getId());

                    UserTask firstNode = getFirstNode(bpmnModelMainProcess);
                    flowTaskOperatorRecordEntityLambdaQueryWrapper.eq(FlowTaskOperatorRecordEntity::getNodeCode,firstNode.getId());
                    FlowTaskOperatorRecordEntity flowTaskOperatorRecordEntity = flowTaskOperatorRecordService.list(flowTaskOperatorRecordEntityLambdaQueryWrapper).get(0);

                    LambdaQueryWrapper<FlowEventLogEntity> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
                    lambdaQueryWrapper1.eq(FlowEventLogEntity::getTaskNodeId,flowTaskOperatorRecordEntity.getTaskNodeId());
                    lambdaQueryWrapper1.orderByDesc(FlowEventLogEntity::getCreatorTime);
                    List<FlowEventLogEntity> flowEventLogEntityList = flowEventLogService.list(lambdaQueryWrapper1);
                    if(CollUtil.isNotEmpty(flowEventLogEntityList)){
                        Boolean failFlag=false;
                        //判断这里面有没有失败的
                        for (FlowEventLogEntity flowEventLogEntity : flowEventLogEntityList) {
                            String respStatus = flowEventLogEntity.getRespStatus();
                            if("2".equals(respStatus)){
                                        failFlag=true;
                            }
                        }

                        for (int i = 0; i < flowEventLogEntityList.size(); i++) {
                            FlowEventLogEntity flowEventLogEntity = flowEventLogEntityList.get(0);
                            TreeCommentSub treeCommentSub = new TreeCommentSub();
                            //最后一个元素
                            if(i==flowEventLogEntityList.size()-1){
                                if(failFlag){
                                    treeCommentSub.setIsRetry(Boolean.TRUE);
                                    treeCommentSub.setResultType(2);
                                }
                                else{
                                    treeCommentSub.setIsRetry(Boolean.FALSE);
                                    treeCommentSub.setResultType(3);
                                }
                            }
                            else{
                                if(failFlag){
                                    treeCommentSub.setIsRetry(Boolean.FALSE);
                                    treeCommentSub.setResultType(3);
                                }
                                else{
                                    treeCommentSub.setResultType(Integer.valueOf(flowEventLogEntity.getRespStatus()));
                                    treeCommentSub.setIsRetry(false);
                                }
                            }
                            //
                            treeCommentSub.setTaskId(historicProcessInstance.getId());
                            treeCommentSub.setNodeCode(historicActivityInstance.getActivityId());
                            treeCommentSub.setNodeType(historicActivityInstance.getActivityType());
                            treeCommentSub.setNodeName(historicActivityInstance.getActivityName());
                            treeCommentSub.setErrorMsg("");
                            treeCommentSub.setStartTime(historicActivityInstance.getStartTime().getTime());
                            if(historicActivityInstance.getEndTime()!=null){
                                treeCommentSub.setEndTime(historicActivityInstance.getEndTime().getTime());
                            }
                            treeCommentSub.setParentId("0");
                            treeCommentSub.setType(1);
                            treeCommentSub.setId(historicActivityInstance.getId());
                            treeCommentSub.setInputStr(flowEventLogEntity.getInputStr());
                            treeCommentSub.setOutputStr(flowEventLogEntity.getOutPutStr());
                            treeCommentSubList.add(treeCommentSub);
                        }

                    }
                }
            }
            else if("endEvent".equals(historicActivityInstance.getActivityType())){
                TreeCommentSub treeCommentSub = new TreeCommentSub();
                treeCommentSub.setTaskId(historicProcessInstance.getId());
                treeCommentSub.setNodeCode(historicActivityInstance.getActivityId());
                treeCommentSub.setNodeType(historicActivityInstance.getActivityType());
                treeCommentSub.setNodeName(historicActivityInstance.getActivityName());
                treeCommentSub.setResultType(3);
                treeCommentSub.setErrorMsg("");
                treeCommentSub.setStartTime(historicActivityInstance.getStartTime().getTime());
                if(historicActivityInstance.getEndTime()!=null){
                    treeCommentSub.setEndTime(historicActivityInstance.getEndTime().getTime());
                }
                treeCommentSub.setParentId("0");
                treeCommentSub.setIsRetry(false);
                treeCommentSub.setType(1);
                treeCommentSub.setId(historicActivityInstance.getId());
                treeCommentSubList.add(treeCommentSub);
            }
        }
        treeCommentMain.setList(treeCommentSubList);
        treeCommentMain.setData("我爱你");
//        IntegrateTaskEntity taskEntity = integrateTaskService.getInfo(id);
//        List<IntegrateNodeEntity> nodeList = integrateNodeService.getList(new ArrayList() {{
//            add(id);
//        }}, null);
//        List<IntegrateTaskModel> list = JsonUtil.getJsonToList(nodeList, IntegrateTaskModel.class);
//        for (IntegrateTaskModel taskModel : list) {
//            boolean isType = "0".equals(taskModel.getParentId());
//            taskModel.setType(isType ? 1 : 0);
//        }
//        IntegrateTaskInfo info = new IntegrateTaskInfo();
//        info.setList(list);
//        info.setData(taskEntity.getData());
        return ActionResult.success(treeCommentMain);
    }

    /**
     * 获取待我审核列表
     *
     * @param category           分类
     * @param paginationFlowTask 分页模型
     * @return
     */
    @Operation(summary = "获取待我审核列表(有带分页)，1-待办事宜，2-已办事宜，3-抄送事宜,4-批量审批")
    @GetMapping("/List/{category}")
    @Parameters({
            @Parameter(name = "category", description = "分类", required = true),
    })
    public ActionResult<PageListVO<FlowBeforeListVO>> list(@PathVariable("category") String category, PaginationFlowTask paginationFlowTask) {
        List<FlowTaskListModel> data = new ArrayList<>();
        paginationFlowTask.setDelegateType(true);
        if (FlowNature.WAIT.equals(category)) {
            data.addAll(flowTaskService.getWaitList(paginationFlowTask));
        } else if (FlowNature.TRIAL.equals(category)) {
            data.addAll(flowTaskService.getTrialList(paginationFlowTask));
        } else if (FlowNature.CIRCULATE.equals(category)) {
            data.addAll(flowTaskService.getCirculateList(paginationFlowTask));
        } else if (FlowNature.BATCH.equals(category)) {
            paginationFlowTask.setIsBatch(1);
            data.addAll(flowTaskService.getWaitList(paginationFlowTask));
        }
        List<FlowBeforeListVO> listVO = new LinkedList<>();
        List<UserEntity> userList = serviceUtil.getUserName(data.stream().map(FlowTaskListModel::getCreatorUserId).collect(Collectors.toList()));
        boolean isBatch = FlowNature.BATCH.equals(category);
        List<FlowTaskNodeEntity> taskNodeList = new ArrayList<>();
        List<String> taskNodeIdList = data.stream().map(FlowTaskListModel::getThisStepId).collect(Collectors.toList());
        if (isBatch) {
            taskNodeList.addAll(flowTaskNodeService.getList(taskNodeIdList, FlowTaskNodeEntity::getId, FlowTaskNodeEntity::getNodePropertyJson));
        }
        for (FlowTaskListModel task : data) {
            FlowBeforeListVO vo = JsonUtil.getJsonToBean(task, FlowBeforeListVO.class);
            //用户名称赋值
            UserEntity user = userList.stream().filter(t -> t.getId().equals(vo.getCreatorUserId())).findFirst().orElse(null);
            vo.setUserName(user != null ? user.getRealName() + "/" + user.getAccount() : "");
            FlowTaskNodeEntity taskNode = taskNodeList.stream().filter(t -> t.getId().equals(task.getThisStepId())).findFirst().orElse(null);
            if (isBatch && taskNode != null) {
                ChildNodeList childNode = JsonUtil.getJsonToBean(taskNode.getNodePropertyJson(), ChildNodeList.class);
                vo.setApproversProperties(JsonUtil.getObjectToString(childNode.getProperties()));
            }
            vo.setFlowVersion(StringUtil.isEmpty(vo.getFlowVersion()) ? "" : vo.getFlowVersion());
            listVO.add(vo);
        }
        PaginationVO paginationVO = JsonUtil.getJsonToBean(paginationFlowTask, PaginationVO.class);
        return ActionResult.page(listVO, paginationVO);
    }

    /**
     * 获取待我审批信息
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "获取待我审批信息")
    @GetMapping("/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult<FlowBeforeInfoVO> info(@PathVariable("id") String id, FlowModel flowModel) throws WorkFlowException {
        flowModel.setId(id);
        FlowBeforeInfoVO vo = flowTaskNewService.getBeforeInfo(flowModel);
        //处理当前默认值
        if (vo != null && vo.getFlowFormInfo() != null && StringUtil.isNotEmpty(vo.getFlowFormInfo().getPropertyJson()) && vo.getFlowFormInfo().getFormType() == 2) {
            UserInfo userInfo = userProvider.get();
            Map<String, Integer> havaDefaultCurrentValue = new HashMap<>();
            vo.getFlowFormInfo().setPropertyJson(setDefaultCurrentValue(vo.getFlowFormInfo().getPropertyJson(), havaDefaultCurrentValue, userInfo));
        }
        return ActionResult.success(vo);
    }

    /**
     * 待我审核审核
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "待我审核审核")
    @PostMapping("/Audit/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult audit(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        LambdaQueryWrapper<FlowTaskOperatorEntity> operatorEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //原本通过taskNodeId 也就是任务id可以唯一定位 此条数据, 因为有委派业务,所以1个任务id可能有多个
        operatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getTaskNodeId,id);
        UserInfo userInfo = userProvider.get();
        if (ObjectUtil.isNotNull(userInfo)) {
            log.info("当前审批人 -> {} -> reqRequest -> {}", userInfo.getUserName(), JsonUtil.getObjectToString(flowModel));
        }
        operatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getHandleId,userInfo.getUserId());
        FlowTaskOperatorEntity operator = flowTaskOperatorService.getOne(operatorEntityLambdaQueryWrapper);

        flowModel.setUserInfo(userInfo);
        FlowTaskEntity flowTask =new FlowTaskEntity();

        FlowModel model = JsonUtil.getJsonToBean(flowModel, FlowModel.class);
        flowTaskNewService.auditAll(flowTask, operator, model);
        return ActionResult.success("审核成功");
    }


    /**
     * 保存草稿
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "保存草稿")
    @PostMapping("/SaveAudit/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult saveAudit(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        LambdaQueryWrapper<FlowTaskOperatorEntity> operatorEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //原本通过taskNodeId 也就是任务id可以唯一定位 此条数据, 因为有委派业务,所以1个任务id可能有多个
        operatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getTaskNodeId,id);
        UserInfo userInfo = userProvider.get();
        operatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getHandleId,userInfo.getUserId());
        FlowTaskOperatorEntity flowTaskOperatorEntity = flowTaskOperatorService.getOne(operatorEntityLambdaQueryWrapper);
        if (flowTaskOperatorEntity != null) {
            Map<String, Object> formDataAll = flowModel.getFormData();
            flowTaskOperatorEntity.setDraftData(JsonUtil.getObjectToString(formDataAll));
            flowTaskOperatorService.update(flowTaskOperatorEntity);
            return ActionResult.success("保存成功");
        }
        return ActionResult.fail(MsgCode.FA001.get());
    }

    /**
     * 审批汇总
     *
     * @param id       主键
     * @param category 类型
     * @param type     类型
     * @return
     */
    @Operation(summary = "审批汇总")
    @GetMapping("/RecordList/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult<List<FlowSummary>> recordList(@PathVariable("id") String id, String category, String type) {
        List<FlowSummary> flowSummaries = flowTaskNewService.recordList(id, category, type);
        return ActionResult.success(flowSummaries);
    }

    /**
     * 待我审核驳回
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "待我审核驳回")
    @PostMapping("/Reject/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult reject(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setId(id);
        flowTaskNewService.reject(flowModel);
        return ActionResult.success("退回成功");
    }

    /**
     * 待我审核转办
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "待我审核转办")
    @PostMapping("/Transfer/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult transfer(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setId(id);
        flowTaskNewService.transfer(flowModel);
        return ActionResult.success("转办成功");
    }

    /**
     * 待我审核委派
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "待我审核委派")
    @PostMapping("/Invoke/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult invoke(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setId(id);
        flowTaskNewService.invoke(flowModel);
        return ActionResult.success("转办成功");
    }


    @Operation(summary = "待我审核终止")
    @PostMapping("/TaskCancel/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult taskCancel(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        LambdaQueryWrapper<FlowTaskOperatorEntity> operatorEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //原本通过taskNodeId 也就是任务id可以唯一定位 此条数据, 因为有委派业务,所以1个任务id可能有多个
        operatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getTaskNodeId,id);
        UserInfo userInfo = userProvider.get();
        operatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getHandleId,userInfo.getUserId());
        FlowTaskOperatorEntity operator = flowTaskOperatorService.getOne(operatorEntityLambdaQueryWrapper);
        flowModel.setUserInfo(userInfo);
        operator.setHandleId(flowModel.getFreeApproverUserId());
        flowTaskNewService.taskCancel(operator, flowModel);
        return ActionResult.success("终止成功");
    }

    @Operation(summary = "待我审核加签")
    @PostMapping("/MultiAdd/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult multiAdd(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        LambdaQueryWrapper<FlowTaskOperatorEntity> operatorEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //原本通过taskNodeId 也就是任务id可以唯一定位 此条数据, 因为有委派业务,所以1个任务id可能有多个
        operatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getTaskNodeId,id);
        UserInfo userInfo = userProvider.get();
        operatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getHandleId,userInfo.getUserId());
        FlowTaskOperatorEntity operator = flowTaskOperatorService.getOne(operatorEntityLambdaQueryWrapper);
        flowModel.setUserInfo(userInfo);
        operator.setHandleId(flowModel.getFreeApproverUserId());
        flowTaskNewService.multiAdd(operator, flowModel);
        return ActionResult.success("加签成功");
    }


    @Operation(summary = "待我审核抄送")
    @PostMapping("/Cc/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult cc(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        LambdaQueryWrapper<FlowTaskOperatorEntity> operatorEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //原本通过taskNodeId 也就是任务id可以唯一定位 此条数据, 因为有委派业务,所以1个任务id可能有多个
        operatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getTaskNodeId,id);
        UserInfo userInfo = userProvider.get();
        operatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getHandleId,userInfo.getUserId());
        FlowTaskOperatorEntity operator = flowTaskOperatorService.getOne(operatorEntityLambdaQueryWrapper);
        flowModel.setUserInfo(userInfo);
        operator.setHandleId(flowModel.getFreeApproverUserId());
        flowTaskNewService.cc(operator, flowModel);
        return ActionResult.success("抄送成功");
    }

    @Operation(summary = "待我审核抄送")
    @PostMapping("/CcBatch/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult ccBatch(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();

        UserInfo userInfo = userProvider.get();
        flowModel.setUserInfo(userInfo);
        Process bpmnModelMainProcess1 = getBpmnModelMainProcess(historicProcessInstance.getProcessDefinitionId());

        UserTask firstNode = getFirstNode(bpmnModelMainProcess1);
        List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery().processInstanceId(historicProcessInstance.getId()).taskDefinitionKey(firstNode.getId()).includeProcessVariables().orderByTaskCreateTime().desc().listPage(0, 1);
        HistoricTaskInstance task = historicTaskInstances.get(0);
        List<String> batchCCUserIds =  flowModel.getBatchCCUserIds();
        List<FlowTaskCirculateEntity> flowTaskCirculateEntityList = new ArrayList<>();
        UserService userService = SpringContextHolder.getBean(UserService.class);
        Map<String, Object> map = task.getProcessVariables();
        for (String batchCCUserId : batchCCUserIds) {
            FlowTaskCirculateEntity circulate = new FlowTaskCirculateEntity();
            circulate.setId(RandomUtil.uuId());
            circulate.setObjectId(batchCCUserId);
            circulate.setNodeCode(task.getTaskDefinitionKey());
            circulate.setNodeName(task.getName());
            circulate.setTaskNodeId(task.getId());
            circulate.setTaskId(task.getProcessInstanceId());

            String applyUserID = MapUtil.getStr(map, APPLY_USER_ID);
            UserEntity userEntity = userService.getInfo(applyUserID);
            circulate.setEnCode(MapUtil.getStr(map,BILL_CODE));
            circulate.setFullName(MapUtil.getStr(map,BUSINESS_TITLE));
            circulate.setTemplateId(MapUtil.getStr(map,FLOW_ENGINE_ID));
            circulate.setFlowId(MapUtil.getStr(map,FLOW_TEMPLATE_JSON_ID));
            circulate.setFlowCategory(MapUtil.getStr(map,PROCESS_CATEGORY));
            circulate.setFlowUrgent(MapUtil.getInt(map,FLOW_URGENT));
            circulate.setCreatorTime(new Date());
            circulate.setApplyUserId(userEntity.getRealName()+"/"+userEntity.getAccount());
            circulate.setApplyUserIdReal(userEntity.getId());
            circulate.setProcessStatus(MapUtil.getInt(map,PROCESS_STATUS));
            flowTaskCirculateEntityList.add(circulate);
        }
        SpringContextHolder.getBean(FlowTaskCirculateService.class).saveBatch(flowTaskCirculateEntityList);

        //1.3调用通知
        String taskProperty = getAttributeValueByTaskDefinitionKey(bpmnModelMainProcess1, task.getTaskDefinitionKey(), "userTask");
        jnpf.engine.model.flowengine.shuntjson.childnode.Properties properties = JSONObject.parseObject(taskProperty, new TypeReference<Properties>() {
        });

        MsgConfig copyMsgConfig = properties.getCopyMsgConfig();
        Integer on = copyMsgConfig.getOn();
        Boolean messageFlag=false;
        if(on!=0){
            messageFlag=true;
        }
        if(messageFlag) {
            FlowMsgModel flowMsgModel = new FlowMsgModel();
            if (CollUtil.isNotEmpty(flowTaskCirculateEntityList)) {
                flowMsgModel.setCirculateList(flowTaskCirculateEntityList);
                flowMsgModel.setCopy(Boolean.TRUE);
            }
            flowMsgModel.setWait(Boolean.FALSE);
            flowMsgModel.setStartNodeProperties(properties);
            flowMsgModel.setCurrentNodeProperties(properties);
//                    flowMsgModel.setNodeList(taskNodeList);
            List<FlowTaskOperatorEntity> operatorEntityList = new ArrayList<>();
            LambdaQueryWrapper<FlowTaskOperatorEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(FlowTaskOperatorEntity::getTaskNodeId, task.getId());
            FlowTaskOperatorEntity operatorServiceOne = flowTaskOperatorService.getOne(lambdaQueryWrapper);
            operatorEntityList.add(operatorServiceOne);
            flowMsgModel.setOperatorList(operatorEntityList);
            flowMsgModel.setData(flowModel.getFormData());
//                    flowMsgModel.setFlowModel(flowModel);
            FlowTaskDTO flowTask = new FlowTaskDTO();
            flowTask.setCreatorUserId(flowModel.getTrueAssignee());
            flowTask.setStatus(FlowTaskStatusEnum.Handle.getCode());
            flowTask.setFullName(MapUtil.getStr(map, BUSINESS_TITLE));
            flowMsgModel.setTaskEntity(flowTask);

            FlowTaskNodeDTO flowTaskNodeDTO = new FlowTaskNodeDTO();
            flowTaskNodeDTO.setTaskId(task.getProcessInstanceId());
            flowTaskNodeDTO.setTaskNodeId(task.getId());
            flowMsgModel.setTaskNodeEntity(flowTaskNodeDTO);

            flowModel.setUserInfo(UserProvider.getUser());
            flowMsgModel.setFlowModel(flowModel);
            FlowTemplateAllModel templateAllModel = flowTaskUtil.templateJson(MapUtil.getStr(map, FLOW_TEMPLATE_JSON_ID));
//                    flowMsgModel.setUserInfo(UserProvider.getUser());
            flowMsgModel.setFlowTemplateAllModel(templateAllModel);
            flowMsgModel.setTaskId(task.getProcessInstanceId());
            flowMsgModel.setTaskNodeId(task.getId());
            SpringContextHolder.getBean(FlowMsgUtil.class).message(flowMsgModel);
        }
        return ActionResult.success("抄送成功");
    }

    /**
     * 待我审核转办
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "待我审核加签")
    @PostMapping("/freeApprover/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult freeApprover(@PathVariable("id") String id, @RequestBody AddMultiFlowModel flowModel) throws WorkFlowException {
        flowModel.setId(id);
        flowTaskNewService.freeApprover(flowModel);
        return ActionResult.success("加签成功");
    }

    /**
     * 待我审核撤回审核
     * 注意：在撤销流程时要保证你的下一节点没有处理这条记录；如已处理则无法撤销流程。
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "待我审核撤回审核")
    @PostMapping("/Recall/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult recall(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
//        FlowTaskOperatorRecordEntity operatorRecord = flowTaskOperatorRecordService.getInfo(id);
//        FlowTaskNodeEntity taskNode = flowTaskNodeService.getInfo(operatorRecord.getTaskNodeId(), FlowTaskNodeEntity::getId);
//        //拒绝不撤回
//        if (FlowNature.ProcessCompletion.equals(operatorRecord.getHandleStatus())) {
//            throw new WorkFlowException("当前流程被退回，无法撤回流程");
//        }
//        if (taskNode == null) {
//            return ActionResult.fail("流程已撤回，不能重复操作！");
//        }
//        if (FlowRecordEnum.swerve.getCode().equals(operatorRecord.getHandleStatus())) {
//            return ActionResult.fail("撤回失败,转向数据无法撤回");
//        }
//        if (FlowRecordEnum.revoke.getCode().equals(operatorRecord.getStatus())) {
//            return ActionResult.fail("流程已撤回，不能重复操作！");
//        }
//        if (taskNode != null && !FlowRecordEnum.revoke.getCode().equals(operatorRecord.getStatus())) {
            flowModel.setUserInfo(userProvider.get());
//        LambdaQueryWrapper<FlowTaskOperatorRecordEntity> flowTaskOperatorEntityLambdaQueryWrapper= new LambdaQueryWrapper<>();
//        flowTaskOperatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorRecordEntity::getTaskNodeId,id);
//        flowTaskOperatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorRecordEntity::getHandleId,userProvider.get().getUserId());
//        FlowTaskOperatorRecordEntity operatorRecord = flowTaskOperatorRecordService.getOne(flowTaskOperatorEntityLambdaQueryWrapper);
            flowTaskNewService.recall(id, flowModel);
//        }
        return ActionResult.success("撤回成功");
    }

    /**
     * 待我审核终止审核
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "待我审核 不同意")
    @PostMapping("/Cancel/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult cancel(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(flowModel.getUserInfo());
        flowTaskNewService.cancel(Collections.singletonList(id), flowModel);
            return ActionResult.success("操作成功");
    }
    @Operation(summary = "待我审核 不同意")
    @PostMapping("/ApprovalCancel/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult approvalCancel(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        List<String> idList = ImmutableList.of(id);
        flowTaskNewService.cancelEx(idList, flowModel);
        return ActionResult.success("操作成功");
    }


    @Operation(summary = "待我审核 弃权")
    @PostMapping("/CounterSignAbstention/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult counterSignAbstention(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        List<String> idList = ImmutableList.of(id);
        flowTaskNewService.counterSignAbstention(idList, flowModel);
        return ActionResult.success("操作成功");
    }

    @Operation(summary = "待我审核 锁定.解锁")
    @PostMapping("/LockOrUnLock/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult lockUnLock(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        List<String> idList = ImmutableList.of(id);
        Integer integer = flowTaskNewService.lockUnLock(idList, flowModel);
        if(integer.equals(1)){
            return ActionResult.success("解锁成功");
        }
        else{
            return ActionResult.success("锁定成功");
        }
    }

    @Operation(summary = "待我审核 锁定.协办")
    @PostMapping("/Assist/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult assist(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        flowTaskNewService.assist(id, flowModel);
        return ActionResult.success("协办成功");

    }
    /**
     * 指派人
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "指派人")
    @PostMapping("/Assign/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult assign(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        flowTaskNewService.assign(id, flowModel);
        return ActionResult.success("指派成功");
    }

    /**
     * 获取候选人
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "获取候选人节点")
    @PostMapping("/Candidates/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult<FlowCandidateVO> candidates(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        FlowCandidateVO candidate = flowTaskNewService.candidates(id, flowModel, false);
        return ActionResult.success(candidate);
    }

    /**
     * 获取候选人
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "获取候选人")
    @PostMapping("/CandidateUser/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult<PageListVO<FlowCandidateUserModel>> candidateUser(@PathVariable("id") String id, @RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        List<FlowCandidateUserModel> candidate = flowTaskNewService.candidateUser(id, flowModel);
        PaginationVO paginationVO = JsonUtil.getJsonToBean(flowModel, PaginationVO.class);
        return ActionResult.page(candidate, paginationVO);
    }

    /**
     * 批量审批引擎
     *
     * @return
     */
    @Operation(summary = "批量审批引擎")
    @GetMapping("/BatchFlowSelector")
    public ActionResult<List<FlowBatchModel>> batchFlowSelector() {
        List<FlowBatchModel> batchFlowList = flowTaskService.batchFlowSelector();
        return ActionResult.success(batchFlowList);
    }

    /**
     * 拒绝下拉框
     *
     * @param id 主键
     * @return
     */
    @Operation(summary = "拒绝下拉框")
    @GetMapping("/RejectList/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult<FlowRejectVO> rejectList(@PathVariable("id") String id) throws WorkFlowException {
        FlowRejectVO vo = flowTaskNewService.rejectList(id, false);
        return ActionResult.success(vo);
    }

    /**
     * 引擎节点
     *
     * @param id 主键
     * @return
     * @throws WorkFlowException
     */
    @Operation(summary = "引擎节点")
    @GetMapping("/NodeSelector/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult<List<FlowBatchModel>> nodeSelector(@PathVariable("id") String id) throws WorkFlowException {
        FlowTemplateAllModel template = flowTaskUtil.templateJson(id);
        String templateJson = template.getTemplateJson().getFlowTemplateJson();
        List<FlowBatchModel> batchList = new ArrayList<>();
        ChildNode childNodeAll = JsonUtil.getJsonToBean(templateJson, ChildNode.class);
        //获取流程节点
        List<ChildNodeList> nodeListAll = new ArrayList<>();
        List<ConditionList> conditionListAll = new ArrayList<>();
        //递归获取条件数据和节点数据
        FlowJsonUtil.getTemplateAll(childNodeAll, nodeListAll, conditionListAll);
        List<String> type = ImmutableList.of(FlowNature.NodeSubFlow, FlowNature.NodeStart);
        for (ChildNodeList childNodeList : nodeListAll) {
            if (!type.contains(childNodeList.getCustom().getType())) {
                FlowBatchModel batchModel = new FlowBatchModel();
                batchModel.setFullName(childNodeList.getProperties().getTitle());
                batchModel.setId(childNodeList.getCustom().getNodeId());
                batchList.add(batchModel);
            }
        }
        return ActionResult.success(batchList);
    }

    /**
     * 流程批量类型下拉
     *
     * @param id 主键
     * @return
     * @throws WorkFlowException
     */
    @Operation(summary = "流程批量类型下拉")
    @GetMapping("/BatchFlowJsonList/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult<List<FlowBatchModel>> batchFlowJsonList(@PathVariable("id") String id) {
        LambdaQueryWrapper<FlowTemplateJsonEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(FlowTemplateJsonEntity::getTemplateId,id);
        lambdaQueryWrapper.orderByDesc(FlowTemplateJsonEntity::getVersion);
        lambdaQueryWrapper.select(FlowTemplateJsonEntity::getVersion,FlowTemplateJsonEntity::getFullName,FlowTemplateJsonEntity::getId);
        List<FlowTemplateJsonEntity> list = flowTemplateJsonService.list(lambdaQueryWrapper);
        List<FlowBatchModel> listVO = new ArrayList<>();
        for (FlowTemplateJsonEntity flowTemplateJsonEntity : list) {
            long count = runtimeService.createProcessInstanceQuery().variableValueEquals(FLOW_TEMPLATE_JSON_ID, flowTemplateJsonEntity.getId()).count();
            FlowBatchModel vo = JsonUtil.getJsonToBean(flowTemplateJsonEntity, FlowBatchModel.class);
            vo.setFullName(vo.getFullName() + "(v" + flowTemplateJsonEntity.getVersion() + ")");
            vo.setNum(count);
            vo.setId(flowTemplateJsonEntity.getId());
            listVO.add(vo);
        }
        return ActionResult.success(listVO);
    }

    /**
     * 批量审批
     *
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "批量审批")
    @PostMapping("/BatchOperation")
    @Parameters({
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult batchOperation(@RequestBody FlowModel flowModel) throws WorkFlowException {
        flowModel.setUserInfo(userProvider.get());
        flowTaskNewService.batch(flowModel);
        return ActionResult.success("批量操作完成");
    }

    /**
     * 批量获取候选人
     *
     * @param flowId         流程主键
     * @param taskOperatorId 代办主键
     * @return
     * @throws WorkFlowException
     */
    @Operation(summary = "批量获取候选人")
    @GetMapping("/BatchCandidate")
    public ActionResult<FlowCandidateVO> batchCandidate(String flowId, String taskOperatorId) throws WorkFlowException {
        FlowModel flowModel = new FlowModel();
        flowModel.setUserInfo(userProvider.get());
        flowModel.setFlowId(flowId);
        FlowCandidateVO candidate = flowTaskNewService.batchCandidates(flowId, taskOperatorId, flowModel);
        return ActionResult.success(candidate);
    }

    /**
     * 消息跳转工作流
     *
     * @param id 主键
     * @return
     */
    @Operation(summary = "消息跳转工作流")
    @GetMapping("/{id}/Info")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult taskOperatorId(@PathVariable("id") String id) throws WorkFlowException {

        LambdaQueryWrapper<FlowTaskCirculateEntity>  flowTaskCirculateEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        flowTaskCirculateEntityLambdaQueryWrapper.eq(FlowTaskCirculateEntity::getId,id);
        FlowTaskCirculateService flowTaskCirculateService = SpringContextHolder.getBean(FlowTaskCirculateService.class);
        FlowTaskCirculateEntity cc = flowTaskCirculateService.getOne(flowTaskCirculateEntityLambdaQueryWrapper);
        String taskId= "";

        if(cc==null){
            FlowTaskOperatorEntity operator = flowTaskOperatorService.getInfo(id);
            taskId = operator.getTaskId();
        }
        else{
            taskId=cc.getTaskId();
            String applyUserIdReal = cc.getApplyUserIdReal();
            LambdaQueryWrapper<FlowTaskOperatorEntity> flowTaskOperatorEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();

            flowTaskOperatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getTaskId,taskId);
            flowTaskOperatorEntityLambdaQueryWrapper.eq(FlowTaskOperatorEntity::getHandleId,applyUserIdReal);
            FlowTaskOperatorEntity operator=flowTaskOperatorService.list(flowTaskOperatorEntityLambdaQueryWrapper).get(0);
        }
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(taskId).singleResult();

        FlowModel flowModel = new FlowModel();
        flowModel.setUserInfo(userProvider.get());
        Map<String, Object> map = new HashMap<>();
        Date endTime = historicProcessInstance.getEndTime();
        if (endTime!=null) {
            map.put("isCheck", true);
        } else {
            map.put("isCheck", false);
        }
        return ActionResult.success(map);
    }

    /**
     * 节点下拉框
     *
     * @param id 主键
     * @return
     */
    @Operation(summary = "节点下拉框")
    @GetMapping("/Selector/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult<List<TaskNodeModel>> selector(@PathVariable("id") String id) {
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
        Process bpmnModelMainProcess = getBpmnModelMainProcess(historicProcessInstance.getProcessDefinitionId());
        Collection<FlowElement> flowElements = bpmnModelMainProcess.getFlowElements();
        List<TaskNodeModel> taskNodeModels= new ArrayList<>();
        UserTask firstNode = BpmnModelUtils.getFirstNode(bpmnModelMainProcess);
        if(historicProcessInstance.getEndTime()==null){
            List<String> activeActivityIds = runtimeService.getActiveActivityIds(historicProcessInstance.getId());
            for (FlowElement flowElement : flowElements) {
                if(flowElement instanceof UserTask){
                    if(!activeActivityIds.contains(flowElement.getId())){
                        TaskNodeModel taskNodeModel= new TaskNodeModel();
                        taskNodeModel.setId(flowElement.getId());
                        taskNodeModel.setNodeName(flowElement.getName());
                        taskNodeModel.setNodeCode(flowElement.getId());
                        taskNodeModels.add(taskNodeModel);
                    }
                }
                if(flowElement instanceof EndEvent){
                    TaskNodeModel taskNodeModel= new TaskNodeModel();
                    taskNodeModel.setId(flowElement.getId());
                    taskNodeModel.setNodeName("流程结束");
                    taskNodeModel.setNodeCode(flowElement.getId());
                    taskNodeModels.add(taskNodeModel);
                }
            }
        }
        else{
            for (FlowElement flowElement : flowElements) {
                if(flowElement instanceof UserTask){
//                    if(!flowElement.getId().equals(firstNode.getId())){
                    TaskNodeModel taskNodeModel= new TaskNodeModel();
                    taskNodeModel.setId(flowElement.getId());
                    taskNodeModel.setNodeName(flowElement.getName());
                    taskNodeModel.setNodeCode(flowElement.getId());
                    taskNodeModels.add(taskNodeModel);
//                    }
                }
            }
        }
        return ActionResult.success(taskNodeModels);
    }

    /**
     * 变更或者复活
     *
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "变更或者复活")
    @PostMapping("/Change")
    @Parameters({
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult change(@RequestBody FlowModel flowModel) throws WorkFlowException {
//        FlowTaskEntity info = flowTaskService.getInfo(flowModel.getTaskId());
//        if (FlowTaskStatusEnum.Revoke.getCode().equals(info.getStatus()) || FlowTaskStatusEnum.Cancel.getCode().equals(info.getStatus()) || FlowTaskStatusEnum.Draft.getCode().equals(info.getStatus())) {
//            throw new WorkFlowException("该流程不能操作");
//        }
        flowModel.setUserInfo(userProvider.get());
        flowTaskNewService.change(flowModel);
        String msg = flowModel.getResurgence() ? "复活成功" : "变更成功";
        return ActionResult.success(msg);
    }

    /**
     * 子流程数据
     *
     * @return
     * 该接口应该有问题
     */
    @Operation(summary = "子流程数据")
    @PostMapping("/SubFlowInfo")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult<List<FlowBeforeInfoVO>> subFlowInfo(@RequestBody SubFlowDTO subFlowDTO) throws WorkFlowException {
        FlowModel flowModel = new FlowModel();


        String isAsync = subFlowDTO.getIsAsync();
        String processInstanceId = subFlowDTO.getProcessInstanceId();
        String nodeId = subFlowDTO.getNodeId();
        List<String> ids = subFlowDTO.getIds();
        //同步
        if("1".equals(isAsync)){
            List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(nodeId).list();
            Set<String> processInstanceIds = new HashSet<>();
            for (HistoricActivityInstance historicActivityInstance : list) {
                processInstanceIds.add(historicActivityInstance.getCalledProcessInstanceId());
            }
            List<HistoricProcessInstance> subList = historyService.createHistoricProcessInstanceQuery().processInstanceIds(processInstanceIds).list();

            List<FlowBeforeInfoVO> vos = new ArrayList<>();
            for (HistoricProcessInstance historicProcessInstance : subList) {
                flowModel.setId(historicProcessInstance.getId());

                LambdaQueryWrapper<FlowTemplateJsonEntity> templateJsonServiceLambdaQueryWrapper = new LambdaQueryWrapper<>();
                templateJsonServiceLambdaQueryWrapper.eq(FlowTemplateJsonEntity::getProcessDefinitionId,historicProcessInstance.getProcessDefinitionId());
                templateJsonServiceLambdaQueryWrapper.select(FlowTemplateJsonEntity::getId);
                FlowTemplateJsonEntity flowTemplateJsonEntity = flowTemplateJsonService.getOne(templateJsonServiceLambdaQueryWrapper);


                flowModel.setFlowId(flowTemplateJsonEntity.getId());
                FlowBeforeInfoVO vo = flowTaskNewService.getBeforeInfo(flowModel);
                vos.add(vo);
            }
            return ActionResult.success(vos);
        }
        //2异步
        else{
            Set<String> set = new HashSet<>();
            set.addAll(ids);
            List<HistoricProcessInstance> subList = historyService.createHistoricProcessInstanceQuery().processInstanceIds(set).list();

            List<FlowBeforeInfoVO> vos = new ArrayList<>();
            for (HistoricProcessInstance historicProcessInstance : subList) {
                flowModel.setId(historicProcessInstance.getId());

                LambdaQueryWrapper<FlowTemplateJsonEntity> templateJsonServiceLambdaQueryWrapper = new LambdaQueryWrapper<>();
                templateJsonServiceLambdaQueryWrapper.eq(FlowTemplateJsonEntity::getProcessDefinitionId,historicProcessInstance.getProcessDefinitionId());
                templateJsonServiceLambdaQueryWrapper.select(FlowTemplateJsonEntity::getId);
                FlowTemplateJsonEntity flowTemplateJsonEntity = flowTemplateJsonService.getOne(templateJsonServiceLambdaQueryWrapper);


                flowModel.setFlowId(flowTemplateJsonEntity.getId());
                FlowBeforeInfoVO vo = flowTaskNewService.getBeforeInfo(flowModel);
                vos.add(vo);
            }
            return ActionResult.success(vos);
        }





    }

    /**
     * 流程类型下拉
     *
     * @param id 主键值
     * @return
     */
    @Operation(summary = "流程类型下拉")
    @GetMapping("/Suspend/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
    })
    public ActionResult suspend(@PathVariable("id") String id) {
//        List<FlowTaskEntity> childList = flowTaskService.getChildList(id, FlowTaskEntity::getId, FlowTaskEntity::getIsAsync);
//        boolean isAsync = childList.stream().filter(t -> FlowNature.ChildAsync.equals(t.getIsAsync())).count() > 0;
        return ActionResult.success(Boolean.FALSE);
    }

    /**
     * 流程挂起
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "流程挂起")
    @PostMapping("/Suspend/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult suspend(@PathVariable("id") String id, @RequestBody FlowModel flowModel) {
        flowModel.setUserInfo(userProvider.get());
        flowTaskNewService.suspend(id, flowModel, true);
        return ActionResult.success("挂起成功");
    }

    /**
     * 流程恢复
     *
     * @param id        主键
     * @param flowModel 流程模型
     * @return
     */
    @Operation(summary = "流程恢复")
    @PostMapping("/Restore/{id}")
    @Parameters({
            @Parameter(name = "id", description = "主键", required = true),
            @Parameter(name = "flowModel", description = "流程模型", required = true),
    })
    public ActionResult restore(@PathVariable("id") String id, @RequestBody FlowModel flowModel) {
        flowModel.setUserInfo(userProvider.get());
        flowModel.setSuspend(false);
        flowTaskNewService.suspend(id, flowModel, false);
        return ActionResult.success("恢复成功");
    }

    //递归处理默认当前配置
    public static String setDefaultCurrentValue(String configJson, Map<String, Integer> havaDefaultCurrentValue, UserInfo userInfo) {
        if (StringUtil.isEmpty(configJson)) {
            return configJson;
        }
        Map<String, Object> configJsonMap = JsonUtil.stringToMap(configJson.trim());
        if (configJsonMap == null && configJsonMap.isEmpty()) {
            return configJson;
        }
        List<UserRelationEntity> userRelationList = staticServiceUtil.getListByUserIdAll(ImmutableList.of(userInfo.getUserId()));

        int isChange = 0;
        //处理字段
        Object fieldsObj = configJsonMap.get("fields");
        List<Map<String, Object>> fieldsList = null;
        if (fieldsObj != null) {
            fieldsList = (List<Map<String, Object>>) fieldsObj;
            if (fieldsList != null && !fieldsList.isEmpty()) {
                setDefaultCurrentValue(userRelationList, fieldsList, userInfo, "add");
                configJsonMap.put("fields", fieldsList);
                isChange = 1;
            }
        }

        if (isChange == 1) {
            return JsonUtil.getObjectToString(configJsonMap);
        } else {
            return configJson;
        }
    }

    public static void setDefaultCurrentValue(List<UserRelationEntity> userRelationList, List<Map<String, Object>> itemList, UserInfo userInfo, String parseFlag) {
        for (int i = 0, len = itemList.size(); i < len; i++) {
            Map<String, Object> itemMap = itemList.get(i);
            if (itemMap == null || itemMap.isEmpty()) {
                continue;
            }
            Map<String, Object> configMap = (Map<String, Object>) itemMap.get("__config__");
            if (configMap == null || configMap.isEmpty()) {
                continue;
            }
            List<Map<String, Object>> childrenList = (List<Map<String, Object>>) configMap.get("children");
            if (childrenList != null && !childrenList.isEmpty()) {
                setDefaultCurrentValue(userRelationList, childrenList, userInfo, parseFlag);
                configMap = (Map<String, Object>) itemMap.get("__config__");
            }
            String jnpfKey = (String) configMap.get("jnpfKey");
            String defaultCurrent = String.valueOf(configMap.get("defaultCurrent"));
            if ("true".equals(defaultCurrent)) {
                Map<String, List<UserRelationEntity>> relationMap = userRelationList.stream().collect(Collectors.groupingBy(UserRelationEntity::getObjectType));
                Object data = "";
                switch (jnpfKey) {
                    case JnpfKeyConsts.COMSELECT:
                        data = new ArrayList() {{
                            add(userInfo.getOrganizeId());
                        }};
                        break;
                    case JnpfKeyConsts.DEPSELECT:
                        data = userInfo.getDepartmentId();
                        break;
                    case JnpfKeyConsts.POSSELECT:
                        data = userInfo.getPositionIds().length > 0 ? userInfo.getPositionIds()[0] : "";
                        break;
                    case JnpfKeyConsts.USERSELECT:
                    case JnpfKeyConsts.CUSTOMUSERSELECT:
                        data = JnpfKeyConsts.CUSTOMUSERSELECT.equals(jnpfKey) ? userInfo.getUserId() + "--" + PermissionConst.USER : userInfo.getUserId();
                        break;
                    case JnpfKeyConsts.ROLESELECT:
                        List<UserRelationEntity> roleList = relationMap.get(PermissionConst.ROLE) != null ? relationMap.get(PermissionConst.ROLE) : new ArrayList<>();
                        data = roleList.size() > 0 ? roleList.get(0).getObjectId() : "";
                        break;
                    case JnpfKeyConsts.GROUPSELECT:
                        List<UserRelationEntity> groupList = relationMap.get(PermissionConst.GROUP) != null ? relationMap.get(PermissionConst.GROUP) : new ArrayList<>();
                        data = groupList.size() > 0 ? groupList.get(0).getObjectId() : "";
                        break;
                    default:
                        break;
                }
                List<Object> list = new ArrayList<>();
                list.add(data);
                if ("search".equals(parseFlag)) {
                    String searchMultiple = String.valueOf(itemMap.get("searchMultiple"));
                    if ("true".equals(searchMultiple)) {
                        configMap.put("defaultValue", list);
                    } else {
                        configMap.put("defaultValue", data);
                    }
                } else {
                    String multiple = String.valueOf(itemMap.get("multiple"));
                    if ("true".equals(multiple)) {
                        configMap.put("defaultValue", list);
                    } else {
                        configMap.put("defaultValue", data);
                    }
                }
                itemMap.put("__config__", configMap);
                itemList.set(i, itemMap);
            }
        }
    }



    /**
     * 获取流程所关联的用户信息
     *
     * @param taskId 任务ID
     * @param flowTaskUserListModel 查询模型
     * @return
     */
    @Operation(summary = "获取流程所关联的用户信息")
    @Parameters({
            @Parameter(name = "taskId", description = "任务ID", required = true),
            @Parameter(name = "flowTaskUserListModel", description = "查询模型", required = true)
    })
    @GetMapping("/TaskUserList/{taskId}")
    public ActionResult getTaskUserList(@PathVariable("taskId") String taskId, FlowTaskUserListModel flowTaskUserListModel)  throws WorkFlowException  {
        FlowUserListModel flowUserListModel = flowTaskUtil.getTaskUserList(taskId);
        List<UserIdListVo> jsonToList = userService.getObjList(flowUserListModel.getAllUserIdList(), flowTaskUserListModel, null);
        PaginationVO paginationVO = JsonUtil.getJsonToBean(flowTaskUserListModel, PaginationVO.class);
        return ActionResult.page(jsonToList, paginationVO);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        staticServiceUtil = this.serviceUtil;
    }
}
